<?php
namespace mirage\core;
if(!defined('MIRAGE_MODE')) die('Forbidden');
use mirage\Mirage;

use mirage\util\CVarDumper;
use mirage\core\SystemException;
use mirage\defaultpage\ErrorController;

/**
 * Description of Router
 * Date Created Aug 30, 2011 9:22:49 PM
 * @author Bryan Salazar
 */
class Router {
   protected static $_instance = null;
   protected $_config;

   protected function Router() {
      $this->_config = Mirage::app()->getConfig();
      $this->start();
   }
   
   public static function route() {
      if(!self::$_instance)
         self::$_instance = new Router();
      return self::$_instance;
   }
   
   protected function start() {
      if(($pos = strpos($_SERVER['REQUEST_URI'], '.php'))) {
         $uri = substr($_SERVER['REQUEST_URI'], $pos + 4);
         if(!$uri || $uri == '/') {
            $this->_callDefaultControllerAndMethod();
         } else {
            $uri = explode('/',$_SERVER['REQUEST_URI']);
            $uri = array_slice($uri,3);
            
//            CVarDumper::dump($_GET,20,true); exit;
            $file = $this->_getControllerFile($uri[0]);
            if(!file_exists($file))
               $this->controllerError($file);
            if(!isset($uri[0])) 
               $this->_callDefaultControllerAndMethod();
            else if(!isset($uri[1]) || $uri[1] == '') {
               Mirage::app()->controller = $uri[0];
               Mirage::app()->method = $uri[1];
               $this->_callControllerAndDefaultMethod($uri[0],$file);
            } else {
               $this->_setParameter($uri);
               $this->_callControllerAndMethod($uri[0], $uri[1], $file);
            }
         }
      } else {
         Mirage::app()->redirect('');
//         $uri = explode('/',$_SERVER['REQUEST_URI']);
         
      }
   }
   
   protected function _setParameter($uri) {
      $paramters = array_slice($uri,2);
      if($paramters && isset($paramters[0]) && $paramters[0] != '/') {
         foreach ($paramters as $value) {
            if(isset($paramters[0]) && isset($paramters[1])) {
               $_GET[$paramters[0]] = $paramters[1];
            }
            $paramters = array_slice($paramters, 2);
            if(!$paramters)
               break;
         }
      }
   }

   protected function _callControllerAndDefaultMethod($controller,$file) {
      Mirage::app()->controller = $controller;
      $controller_name = $this->_getControllerName($controller);
      include_once $file;
      $con = new $controller_name;
      $method = $con->default_method;
      if(!method_exists($con, $method))
         $this->methodError($file);

      Mirage::app()->method = $method;
      $con->$method();
   }
   
   protected function _callControllerAndMethod($controller,$method,$file) {
      Mirage::app()->controller = $controller;
      Mirage::app()->method = $method;
      $controller_name = $this->_getControllerName($controller);
      include_once $file;
      $con = new $controller_name;
      if(!method_exists($con, $method))
         $this->methodError($file);
      
      $con->$method();
   }
   
   protected function controllerError($controller_file) {
      if(MIRAGE_MODE == 'prod') {
         if(!isset ($this->_config['error_page'])) {
            ErrorController::error404();
         } else {
            $error_page = $this->_config['error_page'];
            $controller = ucfirst($error_page['controller']) . 'Controller';
            $method = $error_page['error404'];
            include_once Mirage::app()->getAppPath() . $controller . '.php';
            $con = new $controller;
            $con->$method();
         }
         exit(1);
      } else {
         throw new SystemException($controller_file . ' not exist');
      }
   }

   protected function methodError($controller_file) {
      if(MIRAGE_MODE == 'prod') {
         if(!isset ($this->_config['error_page'])) {
            ErrorController::error404();
         } else {
            $error_page = $this->_config['error_page'];
            $controller = ucfirst($error_page['controller']) . 'Controller';
            $method = $error_page['error404'];
            include_once Mirage::app()->getAppPath() . $controller . '.php';
            $con = new $controller;
            $con->$method();
         }
         exit(1);
      } else {
         throw new SystemException($controller_file . ' method not exist');
      }
   }


   protected function _callDefaultControllerAndMethod() {
      $file = $this->_getControllerFile($this->_config['default_controller']);
      Mirage::app()->controller = $this->_config['default_controller'];
      include_once $file;
      $con = $this->_getControllerName($this->_config['default_controller']);
      if(!class_exists($con))
         throw new SystemException('class ' . $con . ' not exist in ' . $file);
         $controller = new $con;
      if(!$controller instanceof BaseController)
         throw new SystemException($con . ' should have parent of ' . 
                 'BaseController in ' . $file);

      if(!method_exists($controller, $controller->default_method))
         throw new SystemException('default method "' . $controller->default_method . '"' .
                 ' method not exist in ' . $file);
      $method = $controller->default_method;
      Mirage::app()->method = $method;
      $controller->$method();
   }

   protected function _getControllerName($con) {
      return ucfirst($con) . 'Controller';
   }
   
   protected function _getControllerFile($con) {
      return Mirage::app()->getAppPath() . '/controllers/' .
         $this->_getControllerName($con) . '.php';
   }
}
